package com.sos.utils
{
	public class ErrorUtils
	{
		
		// -------------------------------------------------------------------------------
		// FIELDS
		// -------------------------------------------------------------------------------
		
		private static var _debugStackRegExp:RegExp = /at\x20(.+?)\[(.+?)\]/i;
		
		// -------------------------------------------------------------------------------
		// PRIVATE METHODS
		// -------------------------------------------------------------------------------
		
		private static function parseStackLine(stackLine:String, inDebug:Boolean):Object
		{
			
			// LT_TODO: aggiungere il controllo per metodo statico, basta controllare
			// la presenza del $ alla fine del nome della classe
			
			// Locals 
			var file:String = "";
			var klas:String = "";
			var func:String = "";
			var line:int 	= 0;
			// Retrieve the file
			if(inDebug)
			{
				// Splits the stack entry
				var matches:Array = _debugStackRegExp.exec(stackLine);
				// Retrieve file and line
				file = matches[1];
				line = matches[2].split(':')[2]; // 2 to avoid : of drive path
			}
			else
			{
				file = (stackLine).substring(4); // Skip first 4 characters
				line = 0;
			}
			// Parses the file to extract class name and function
			var namespaceIndex:int = file.indexOf("::");
			if (namespaceIndex > -1)
			{
				var klasIndex:int = file.indexOf("/", namespaceIndex + 2);
				if (klasIndex > -1)
				{
					var funcIndex:int = file.indexOf(")", klasIndex);	
					if (funcIndex > -1)
					{
						klas = file.substring(0, klasIndex);
						func = file.substring(klasIndex + 1, funcIndex + 1);
					}
				}
			}
			return { file: file, klass: klas, funct: func, line: line};
		}
		
		// -------------------------------------------------------------------------------
		// PUBLIC METHODS
		// -------------------------------------------------------------------------------
		
		public static function toString(error:Error):String
		{
			if (error) return ClassUtils.getName(error) + ": " + error.message;
			else return "<null>";
		}
		
		public static function toArray(error:Error):Array
		{
			var stack:Array = error.getStackTrace().split("\n");
			var array:Array = new Array();
			for (var i:int = 0; i < stack.length; i++)
			{
				array.push(stack[i]);
			}
			return array;
		}
		
		public static function parse(error:Error):Array
		{
			// Locals
			var stack:Array 		= null;
			var inDebug:Boolean 	= false;
			var callIndex:int		= 1;
			var callerIndex:int		= 2;
			
			// Retrieve the stack from the error
			var stackTrace:String 	= error.getStackTrace();
			// Parse the stack
			stack = stackTrace.split("\n");
			// Check if the execution is in debug using the first valid stack line
			inDebug = (stack[callIndex] as String).indexOf('[') != -1;
			
			// Parse the current call
			var callData:Object = parseStackLine(stack[callIndex] as String, inDebug);
			// Parse the caller
			var callerData:Object = parseStackLine(stack[callerIndex] as String, inDebug);
			
			// Dump lines
			var dump:Array = new Array();
			dump.push(error.message);
			dump.push(error.name + " (id: " + error.errorID + ")");
			dump.push("Call: " + inDebug ? callData.file + " [" + callData.line + "]" : callData.file);
			dump.push("Caller: "+ inDebug ? callerData.file + " [" + callerData.line + "]" : callerData.file);
			dump.push("STACK TRACE");
			for (var i:int = 1; i < stack.length; i++)
			{
				dump.push("\t" + stack[i]);	
			}
			return dump;
		}
		
		
	}
}